/** 
 * METRIC S
 * Contains 
 * ENGLISH BASE:
 * Each unit is set up as:
 * 
 * S {
 * 
 * 	-- Returns value in same units --
 * 	public double tos(double value){
 * 		return value;
 * 	}
 * 
 * 	-- Returns value in other units --
 * 	-- One method for each type in category --
 * 	-- Example: S = INCHES, value = BASE_TO_SQUARE_INCHES8, Convert toFeet, Return = BASE_TO_SQUARE_INCHES.BASE_TO_CUBIC_INCHES (Feet)
 * 	public double toOthers(double value){
 * 		return value ( / or * ) ####;
 * 	}
 * 		
 * 	-- Converts value value of  type u into S type --
 * 	-- Example: S = INCHES, value = BASE_TO_SQUARE_INCHES.BASE_TO_CUBIC_INCHES, u = FEET, return = BASE_TO_SQUARE_INCHES8 (Inches)
 * 	public double convert (double value, English u){
 * 		return u.tos(value);
 *	}
 * }
 */

package umuc.cmsc495.mach2.unit;

/**
 * @author Michael Swann
 */
public enum MetricUnit {
    KILO {
	@Override
	public double toKilo(double value) {
	    return value;
	}

	@Override
	public double toHecto(double value) {
	    return value * 10;
	}

	@Override
	public double toDeca(double value) {
	    return value * 100;
	}

	@Override
	public double toBase(double value) {
	    return value * 1000;
	}

	@Override
	public double toDeci(double value) {
	    return value * 10000;
	}

	@Override
	public double toCenti(double value) {
	    return value * 100000;
	}

	@Override
	public double toMilli(double value) {
	    return value * 1000000;
	}

	@Override
	public double toEnglishSquareInches(double value) {
	    return (BASE_TO_SQUARE_INCHES / 1000) * value;
	}

	@Override
	public double toEnglishDryQuarts(double value) {
	    return (BASE_TO_DRYQUARTS / 1000) * value;
	}

	@Override
	public double toEnglishInches(double value) {
	    return (BASE_TO_INCHES / 1000) * value;
	}

	@Override
	public double toEnglishOunces(double value) {
	    return (BASE_TO_OUNCES / 1000) * value;
	}

	@Override
	public double toEnglishCubicInches(double value) {
	    return (BASE_TO_CUBIC_INCHES / 1000) * value;
	}

	@Override
	public double toEnglishWetQuarts(double value) {
	    return (BASE_TO_WETQUARTS_INCHES / 1000) * value;
	}

	@Override
	public double convert(double value, MetricUnit u) {
	    return u.toKilo(value);
	}
    },

    HECTO {
	@Override
	public double toKilo(double value) {
	    return value / 10;
	}

	@Override
	public double toHecto(double value) {
	    return value;
	}

	@Override
	public double toDeca(double value) {
	    return value * 10;
	}

	@Override
	public double toBase(double value) {
	    return value * 100;
	}

	@Override
	public double toDeci(double value) {
	    return value * 1000;
	}

	@Override
	public double toCenti(double value) {
	    return value * 10000;
	}

	@Override
	public double toMilli(double value) {
	    return value * 100000;
	}

	@Override
	public double toEnglishSquareInches(double value) {
	    return (BASE_TO_SQUARE_INCHES / 100) * value;
	}

	@Override
	public double toEnglishDryQuarts(double value) {
	    return (BASE_TO_DRYQUARTS / 100) * value;
	}

	@Override
	public double toEnglishInches(double value) {
	    return (BASE_TO_INCHES / 100) * value;
	}

	@Override
	public double toEnglishOunces(double value) {
	    return (BASE_TO_OUNCES / 100) * value;
	}

	@Override
	public double toEnglishCubicInches(double value) {
	    return (BASE_TO_CUBIC_INCHES / 100) * value;
	}

	@Override
	public double toEnglishWetQuarts(double value) {
	    return (BASE_TO_WETQUARTS_INCHES / 100) * value;
	}

	@Override
	public double convert(double value, MetricUnit u) {
	    return u.toHecto(value);
	}
    },

    DECA {
	@Override
	public double toKilo(double value) {
	    return value / 100;
	}

	@Override
	public double toHecto(double value) {
	    return value / 10;
	}

	@Override
	public double toDeca(double value) {
	    return value;
	}

	@Override
	public double toBase(double value) {
	    return value * 10;
	}

	@Override
	public double toDeci(double value) {
	    return value * 100;
	}

	@Override
	public double toCenti(double value) {
	    return value * 1000;
	}

	@Override
	public double toMilli(double value) {
	    return value * 10000;
	}

	@Override
	public double toEnglishSquareInches(double value) {
	    return (BASE_TO_SQUARE_INCHES / 10) * value;
	}

	@Override
	public double toEnglishDryQuarts(double value) {
	    return (BASE_TO_DRYQUARTS / 10) * value;
	}

	@Override
	public double toEnglishInches(double value) {
	    return (BASE_TO_INCHES / 10) * value;
	}

	@Override
	public double toEnglishOunces(double value) {
	    return (BASE_TO_OUNCES / 10) * value;
	}

	@Override
	public double toEnglishCubicInches(double value) {
	    return (BASE_TO_CUBIC_INCHES / 10) * value;
	}

	@Override
	public double toEnglishWetQuarts(double value) {
	    return (BASE_TO_WETQUARTS_INCHES / 10) * value;
	}

	@Override
	public double convert(double value, MetricUnit u) {
	    return u.toDeca(value);
	}
    },

    BASE {
	@Override
	public double toKilo(double value) {
	    return value / 1000;
	}

	@Override
	public double toHecto(double value) {
	    return value / 100;
	}

	@Override
	public double toDeca(double value) {
	    return value / 10;
	}

	@Override
	public double toBase(double value) {
	    return value;
	}

	@Override
	public double toDeci(double value) {
	    return value * 10;
	}

	@Override
	public double toCenti(double value) {
	    return value * 100;
	}

	@Override
	public double toMilli(double value) {
	    return value * 1000;
	}

	@Override
	public double toEnglishSquareInches(double value) {
	    return value * BASE_TO_SQUARE_INCHES;
	}

	@Override
	public double toEnglishDryQuarts(double value) {
	    return value * BASE_TO_DRYQUARTS;
	}

	@Override
	public double toEnglishInches(double value) {
	    return value * BASE_TO_INCHES;
	}

	@Override
	public double toEnglishOunces(double value) {
	    return value * BASE_TO_OUNCES;
	}

	@Override
	public double toEnglishCubicInches(double value) {
	    return value * BASE_TO_CUBIC_INCHES;
	}

	@Override
	public double toEnglishWetQuarts(double value) {
	    return value * BASE_TO_WETQUARTS_INCHES;
	}

	@Override
	public double convert(double value, MetricUnit u) {
	    return u.toBase(value);
	}
    },

    DECI {
	@Override
	public double toKilo(double value) {
	    return value / 10000;
	}

	@Override
	public double toHecto(double value) {
	    return value / 1000;
	}

	@Override
	public double toDeca(double value) {
	    return value / 100;
	}

	@Override
	public double toBase(double value) {
	    return value / 10;
	}

	@Override
	public double toDeci(double value) {
	    return value;
	}

	@Override
	public double toCenti(double value) {
	    return value * 10;
	}

	@Override
	public double toMilli(double value) {
	    return value * 100;
	}

	@Override
	public double toEnglishSquareInches(double value) {
	    return (BASE_TO_SQUARE_INCHES * 10) * value;
	}

	@Override
	public double toEnglishDryQuarts(double value) {
	    return (BASE_TO_DRYQUARTS * 10) * value;
	}

	@Override
	public double toEnglishInches(double value) {
	    return (BASE_TO_INCHES * 10) * value;
	}

	@Override
	public double toEnglishOunces(double value) {
	    return (BASE_TO_OUNCES * 10) * value;
	}

	@Override
	public double toEnglishCubicInches(double value) {
	    return (BASE_TO_CUBIC_INCHES * 10) * value;
	}

	@Override
	public double toEnglishWetQuarts(double value) {
	    return (BASE_TO_WETQUARTS_INCHES * 10) * value;
	}

	@Override
	public double convert(double value, MetricUnit u) {
	    return u.toDeci(value);
	}
    },
    CENTI {
	@Override
	public double toKilo(double value) {
	    return value / 100000;
	}

	@Override
	public double toHecto(double value) {
	    return value / 10000;
	}

	@Override
	public double toDeca(double value) {
	    return value / 1000;
	}

	@Override
	public double toBase(double value) {
	    return value / 100;
	}

	@Override
	public double toDeci(double value) {
	    return value / 10;
	}

	@Override
	public double toCenti(double value) {
	    return value;
	}

	@Override
	public double toMilli(double value) {
	    return value * 10;
	}

	@Override
	public double toEnglishSquareInches(double value) {
	    return (BASE_TO_SQUARE_INCHES * 100) * value;
	}

	@Override
	public double toEnglishDryQuarts(double value) {
	    return (BASE_TO_DRYQUARTS * 100) * value;
	}

	@Override
	public double toEnglishInches(double value) {
	    return (BASE_TO_INCHES * 100) * value;
	}

	@Override
	public double toEnglishOunces(double value) {
	    return (BASE_TO_OUNCES * 100) * value;
	}

	@Override
	public double toEnglishCubicInches(double value) {
	    return (BASE_TO_CUBIC_INCHES * 100) * value;
	}

	@Override
	public double toEnglishWetQuarts(double value) {
	    return (BASE_TO_WETQUARTS_INCHES * 100) * value;
	}

	@Override
	public double convert(double value, MetricUnit u) {
	    return u.toCenti(value);
	}
    },
    MILLI {
	@Override
	public double toKilo(double value) {
	    return value / 1000000;
	}

	@Override
	public double toHecto(double value) {
	    return value / 100000;
	}

	@Override
	public double toDeca(double value) {
	    return value / 10000;
	}

	@Override
	public double toBase(double value) {
	    return value / 1000;
	}

	@Override
	public double toDeci(double value) {
	    return value / 100;
	}

	@Override
	public double toCenti(double value) {
	    return value / 10;
	}

	@Override
	public double toMilli(double value) {
	    return value;
	}

	@Override
	public double toEnglishSquareInches(double value) {
	    return (BASE_TO_SQUARE_INCHES * 1000) * value;
	}

	@Override
	public double toEnglishDryQuarts(double value) {
	    return (BASE_TO_DRYQUARTS * 1000) * value;
	}

	@Override
	public double toEnglishInches(double value) {
	    return (BASE_TO_INCHES * 1000) * value;
	}

	@Override
	public double toEnglishOunces(double value) {
	    return (BASE_TO_OUNCES * 1000) * value;
	}

	@Override
	public double toEnglishCubicInches(double value) {
	    return (BASE_TO_CUBIC_INCHES * 1000) * value;
	}

	@Override
	public double toEnglishWetQuarts(double value) {
	    return (BASE_TO_WETQUARTS_INCHES * 1000) * value;
	}

	@Override
	public double convert(double value, MetricUnit u) {
	    return u.toMilli(value);
	}
    };

    private static final double BASE_TO_SQUARE_INCHES    = 1550.0031;
    private static final double BASE_TO_DRYQUARTS	= 0.9080829782;
    private static final double BASE_TO_INCHES	   = 39.3700787;
    private static final double BASE_TO_OUNCES	   = 0.0352739619;
    private static final double BASE_TO_CUBIC_INCHES     = 61023.7441;
    private static final double BASE_TO_WETQUARTS_INCHES = 1.05668821;

    /**
     * @param sourceValve
     *            Value in Source s
     * @param source
     *            Source Type
     * @return Value in Target s
     */
    public abstract double toKilo(double value);

    public abstract double toHecto(double value);

    public abstract double toDeca(double value);

    public abstract double toBase(double value);

    public abstract double toDeci(double value);

    public abstract double toCenti(double value);

    public abstract double toMilli(double value);

    public abstract double toEnglishSquareInches(double value);

    public abstract double toEnglishDryQuarts(double value);

    public abstract double toEnglishInches(double value);

    public abstract double toEnglishOunces(double value);

    public abstract double toEnglishCubicInches(double value);

    public abstract double toEnglishWetQuarts(double value);

    public abstract double convert(double sourceValve, MetricUnit source);
}
